/*
 * Esta clase debe contener los metodo insert, delete, update y Find conectados a la Interfase.
 * Para ello extiende como super clase Beans, que contiende todos los atributos de la tabla
 * De requerirse algun atributo que no lo contemple Beas, este debe ser creado aquí
 * 
 */
package person.user;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.el.ELContext;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import system.general.*;

/**
 *
 * @author emojica
 */
@ManagedBean(name = "person_user")
@RequestScoped
public class Main extends Beans {

    Logged logged;
    private Persistencia persistencia = new Persistencia();
    private Cryptography crypto = new Cryptography();
    private Message msg = new Message();
    private person.general.Find person_generalFind = new person.general.Find();
    private List<person.general.Beans> person_generalList = new ArrayList<>();
    private Find person_userFind = new Find();
    private List<Beans> person_userList = new ArrayList<>();
    private String sql;
    private Map<String, String> map = new LinkedHashMap<>();

    public Main() {
        ELContext elContext = FacesContext.getCurrentInstance().getELContext();
        logged = (Logged) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, "logged");
        namePackage();
        load();
    }

    /**
     * Método utilizado para desplegar la información de un resitro que ha sido
     * seleccionado. Para ello requiere que el id del registro haya sido
     * asignado a la variable RecordId del logged. En este caso particular, el
     * usuario es localizado por el id_persona.
     */
    private void load() {
        try {
            //Verifica si hay un registro seleccionado
            if (logged.getMasterId() == 0) {
                return;
            }

            map.clear();
            map.put("id_persona = " + logged.getMasterId(), " ");

            person_userList.clear();
            person_userList = person_userFind.byMap(map);
            if (person_userList.isEmpty()) {
                return;
            }

            setNombre(person_userList.get(0).getNombre());
            setClave(person_userList.get(0).getClave());
            setIdioma(person_userList.get(0).getIdioma());
            setLogin(person_userList.get(0).getLogin());
            setUnLogin(person_userList.get(0).getUnLogin());
            setRegistrado(person_userList.get(0).getRegistrado());
            setActivo(person_userList.get(0).getActivo());


        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
        } finally {
        }
    }

    /**
     * Método utilizado para INSERTAR O ACTUALIZAR un registro. Para ello
     * requiere que el id del registro haya sido asignado a la variable RecordId
     * del logged. En este caso en particular, el usuario es localizado por el
     * id_persona.
     */
    public void update() {
        try {

            if (logged.getMasterId() == 0) {
                throw new Exc("m4");
            }
            //Verifica si hay registros seleccionados
            if (logged.getDetailId() == 0) {
                throw new Exc("m6");
            }

            //Verifica si el usuario existe para otra persona
            map.clear();
            map.put("id_persona <> " + logged.getMasterId(), " AND ");
            map.put("lower(nombre) = '" + getNombre().toLowerCase(), "' ");
            if (person_userFind.byExist(map)) {
                throw new Exc("m5");
            }

            //Verifica si el usuario ha sido creado para la persona y lo actualiza
            //de lo contrario inserta el registro
            map.clear();
            map.put("id_persona = " + logged.getMasterId(), " ");
            if (person_userFind.byExist(map)) {
                sql = "UPDATE public.persona_usuario SET "
                        + "nombre = '" + getNombre() + "',  "
                        + "clave = '" + crypto.encryption(getClave()) + "', "
                        + "idioma  = '" + getIdioma().toLowerCase() + "', "
                        + "activo = '" + getActivo() + "'  "
                        + "WHERE id_persona =" + logged.getMasterId();

                //Actualiza la información del registro
                persistencia.executeUpdate(sql);

            } else {
                sql = "INSERT INTO public.persona_usuario (id_persona, nombre,clave,idioma,login,unlogin,registrado,activo) "
                        + "VALUES ("
                        + logged.getMasterId() + ", "
                        + "'" + getNombre() + "',  "
                        + "'" + crypto.encryption(getClave()) + "', "
                        + "'" + getIdioma().toLowerCase() + "', "
                        + "CURRENT_TIMESTAMP, "
                        + "CURRENT_TIMESTAMP, "
                        + "CURRENT_TIMESTAMP, "
                        + "'" + getActivo() + "')";

                //Inserta la información del registro
                persistencia.executeUpdate(sql);
            }

            throw new Exc("m2");

        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
        } finally {
        }
    }

    public void delete() {
        try {

            //Verifica si hay registros seleccionados
            if (logged.getMasterId() == 0) {
                throw new Exc("m4");
            }

            //Elimina el resgistro por el id_persona
            deleteByIdPersona(logged.getMasterId());

            throw new Exc("m3");

        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
        } finally {
        }
    }

    public String login() {
        try {

            //Consulta si el usuario y clave existen
            map.clear();
            map.put("lower(nombre) = '" + getNombre().toLowerCase(), "' AND ");
            map.put("clave = '" + crypto.encryption(getClave()), "' ");
            person_userList = person_userFind.byMap(map);
            if (person_userList.isEmpty()) {
                throw new Exc("m21");
            }

            //Consulta la información de la persona
            map.clear();
            map.put("id = " + person_userList.get(0).getId_persona(), " ");
            person_generalList = person_generalFind.byMap(map);

            //logged.clear();
            logged.setLoggedId(person_generalList.get(0).getId());
            logged.setLoggedName(person_generalList.get(0).getNombre() + " " + person_generalList.get(0).getApellido());
            logged.setLoggedIdiom(person_userList.get(0).getIdioma());

            //Actualiza la fecha y hora del login
            loginDate();

            return "/faces/home.xhtml?faces-redirect=true";

        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
            return "/page/person/user/login.xhtml";
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
            return "/page/person/user/login.xhtml";
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
            return "/page/person/user/login.xhtml";
        } finally {
        }
    }

    public String unLogin() {
        //Actualiza la fecha y hora de cerrar session
        unLoginDate();
        logged.clearAll();
        return "/page/person/user/login.xhtml";

    }

    public void loginDate() {
        try {
            sql = "UPDATE public.persona_usuario SET "
                    + "login = CURRENT_TIMESTAMP "
                    + "WHERE id =" + logged.getLoggedId();

            //Actualiza la información del registro
            persistencia.executeUpdate(sql);

        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
        } finally {
        }
    }

    public void unLoginDate() {
        try {
            sql = "UPDATE public.persona_usuario SET "
                    + "unlogin = CURRENT_TIMESTAMP "
                    + "WHERE id =" + logged.getLoggedId();

            //Actualiza la información del registro
            persistencia.executeUpdate(sql);

        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
        } finally {
        }
    }

    public void deleteByIdUsuario(int id_usuario) throws Exc, SQLException, Exception {
        //Verifica si el usuario ya existe para otra persona
        sql = "DELETE FROM public.persona_usuario "
                + "WHERE id_usuario = " + id_usuario;
        persistencia.executeUpdate(sql);
    }

    public void deleteByIdPersona(int id_persona) throws Exc, SQLException, Exception {
        //Verifica si el usuario ya existe para otra persona
        sql = "DELETE FROM public.persona_usuario "
                + "WHERE id_persona = " + id_persona;
        persistencia.executeUpdate(sql);
    }

    public void restartKey() {
        try {
            //Verifica si hay registros seleccionados
            if (logged.getMasterId() != 0) {
                throw new Exc("m2");
            }
            sql = "UPDATE public.persona_usuario SET "
                    + "clave = '" + crypto.encryption("12345") + "' "
                    + "WHERE id_usuario =" + logged.getMasterId();

            //Actualiza la información del registro seleccionado
            persistencia.executeUpdate(sql);

            throw new Exc("m2");

        } catch (Exc ex) {
            msg.showMsg(namePackage(), "system", ex.getIdError());
        } catch (SQLException ex) {
            msg.showErr(namePackage(), "sql", ex);
        } catch (Exception ex) {
            msg.showErr(namePackage(), "java", ex);
        } finally {
        }
    }

    public void clear() {
        logged.setMasterId(0);
        clearBeans();
    }

    private String namePackage() {
        Package pack = this.getClass().getPackage();
        return pack.getName();
    }
}
